﻿using CommonLibrary.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CommonLibrary
{
    public class SqlClauses
    {
        public static readonly SqlClause InsertInto = new SqlClause("insert into", " ,", " {0}(", ")");
        public static readonly SqlClause Values = new SqlClause(" values", ",", "(", ")");
    }

    public class SampleSqlBuilder : ISqlBuilder
    {
        private StringBuilder _buffer = new StringBuilder();
        private Dictionary<string, IDbDataParameter> _parameters =
            new Dictionary<string, IDbDataParameter>();
        private SqlClause _lastClause = null;
        private string _end = null;

        public IDbDataParameter[] Parameters { get { return _parameters.Values.ToArray(); } }
        public StringBuilder Buffer { get { return _buffer; } }

        public void Clear()
        {
            _buffer.Clear();
            _parameters.Clear();
        }

        public ISqlBuilder InsertInto(SqlName table, params SqlName[] columns)
        {
            return this.AppendClause(
                SqlClauses.InsertInto,
                string.Format(SqlClauses.InsertInto.StartFormat, table),
                columns);
        }

        public ISqlBuilder Values(params SqlValue[] args)
        {
            foreach (var i in args)
            {
                if (i.Parameter != null)
                    this._parameters[i.Parameter.ParameterName] = i.Parameter;
            }

            return this.AppendClause(
                SqlClauses.Values,
                SqlClauses.Values.StartFormat,
                args);
        }

        public ISqlBuilder Update(SqlName table)
        {
            return this;
        }

        public ISqlBuilder Set(params KeyValuePair<SqlName, SqlValue>[] args)
        {
            return this;
        }

        public ISqlBuilder Delete(SqlName table)
        {
            return this;
        }

        public ISqlBuilder Select(params SqlName[] columns)
        {
            return this;
        }

        public ISqlBuilder From(SqlName table)
        {
            return this;
        }

        public ISqlBuilder Where(string condition)
        {
            return this;
        }

        public ISqlBuilder OrderByAsc(params SqlName[] columns)
        {
            return this;
        }

        public ISqlBuilder OrderByDesc(params SqlName[] columns)
        {
            return this;
        }

        public ISqlBuilder GroupBy(params SqlName[] columns)
        {
            return this;
        }

        public ISqlBuilder Having(string condition)
        {
            return this;
        }

        public ISqlBuilder InnerJoin(SqlName table)
        {
            return this;
        }

        public ISqlBuilder LeftJoin(SqlName table)
        {
            return this;
        }

        public ISqlBuilder FullJoin(SqlName table)
        {
            return this;
        }

        public ISqlBuilder On(string condition)
        {
            return this;
        }

        public ISqlBuilder AppendQuery(ISqlBuilder builder)
        {
            return this;
        }

        public ISqlBuilder AppendQuery(string query)
        {
            this.End();
            this._buffer.Append(query);
            return this;
        }

        public void AddParamter(IDbDataParameter parameter)
        {
            this._parameters[parameter.ParameterName] = parameter;
        }

        public string Escape(string input)
        {
            return input;
        }

        public override string ToString()
        {
            //this.End();
            return this._buffer.ToString();
        }

        private ISqlBuilder AppendClause(
            SqlClause clause,
            string format,
            params object[] args)
        {
            // 如果上一个符号与当前符号相同
            if (clause == this._lastClause)
            {
                // 追加内容
                this._buffer.Append(clause.Separator);
                if (args != null && args.Length != 0)
                {
                    this._buffer.Append(args[0].ToString());
                    for (int i = 1; i < args.Length; i++)
                    {
                        if (clause.Separator != null)
                            this._buffer.Append(clause.Separator);

                        this._buffer.Append(args[i].ToString());
                    }
                }
            }
            else
            {
                // 新操作符
                // 非首次执行则, 则新起一行
                // 如果可能，对上次符号进行闭合
                if (this._lastClause != null)
                {
                    this.End();
                    this._buffer.Append(Environment.NewLine);
                }

                // 新内容
                this._buffer.Append(clause.Name);
                this._buffer.Append(' ');
                this._buffer.Append(format);
                if (args != null && args.Length != 0)
                {
                    this._buffer.Append(args[0].ToString());
                    for (int i = 1; i < args.Length; i++)
                    {
                        if (clause.Separator != null)
                            this._buffer.Append(clause.Separator);

                        this._buffer.Append(args[i].ToString());
                    }
                }                
            }

            this._lastClause = clause;
            if (this._lastClause == null)
                throw new ArgumentException("");
            this._end = clause.EndFormat;

            return this;
        }

        public void End()
        {
            if (_end != null)
            {
                this._buffer.Append(_end);
                this._end = null;
                this._lastClause = null;
            }
        }
    }
}
